home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Personal Computer World 2009 February
/
PCWFEB09.iso
/
Software
/
Resources
/
Chat & Communication
/
Digsby build 37
/
digsby_setup.exe
/
lib
/
gui
/
uberwidgets
/
umenu.pyo
(
.txt
)
< prev
Wrap
Python Compiled Bytecode
|
2008-10-13
|
43KB
|
1,343 lines
# Source Generated with Decompyle++
# File: in.pyo (Python 2.5)
from __future__ import with_statement
from gui.skin.skinobjects import SkinColor
import wx
from wx import RectPS, Rect, ITEM_NORMAL, ITEM_SEPARATOR, ITEM_CHECK, ITEM_RADIO, Point, ALIGN_CENTER_VERTICAL, FindWindowAtPoint, MenuItem, CallLater, FindWindowAtPointer, GetMousePosition, wxEVT_MOTION, StockCursor, CURSOR_DEFAULT, GetMouseState, Window
from wx import PyCommandEvent, wxEVT_MENU_OPEN
from gui import skin
from traceback import print_exc
from gui.textutil import default_font
from gui.windowfx import fadein
from gui.vlist.skinvlist import SkinVListBox
from gui.uberwidgets.UberButton import UberButton
from gui.skin.skinobjects import Margins
from gui.uberwidgets.skinnedpanel import SkinnedPanel
from gui.uberwidgets.keycatcher import KeyCatcher
from cgui import SplitImage4
from gui.toolbox import Monitor
from util import traceguard, memoize, Delegate, Storage as S, InstanceTracker
from common import prefprop
from weakref import ref
from logging import getLogger
log = getLogger('umenu')
wxMSW = 'wxMSW' in wx.PlatformInfo
WM_INITMENUPOPUP = 279
def MenuItem_repr(item):
text = None if item.IsSeparator() else item.Label
return '<%s %s>' % (item.__class__.__name__, text)
MenuItem.__repr__ = MenuItem_repr
del MenuItem_repr
MenuItem.SetCallback = lambda item, callback: item.Menu.SetCallback(item.Id, callback)
class UMenuTrayTimer(wx.Timer):
def __init__(self, umenu):
wx.Timer.__init__(self)
self.umenu = umenu
def Notify(self):
try:
mp = GetMousePosition()
ms = GetMouseState()
except Exception:
return None
if not ms.LeftDown() and ms.RightDown() or ms.MiddleDown():
return None
menu = self.umenu
while menu != None:
if menu.ScreenRect.Contains(mp):
return None
continue
submenu = menu.menu._childmenu
menu = None if submenu is not None else None
self.Stop()
self.umenu.Dismiss()
class UMenu(wx.Menu, InstanceTracker):
last_menu = None
def __init__(self, parent, label = '', id = None, onshow = None, windowless = None):
if not isinstance(parent, wx.WindowClass):
raise TypeError('UMenu parent must be a wx.Window')
wx.Menu.__init__(self, label)
InstanceTracker.track(self)
if not isinstance(id, (int, type(None))):
raise TypeError
self._parentmenu = None
self._childmenu = None
self.Id = None if id is None else id
self.Window = parent
self.OnDismiss = Delegate()
self.cbs = { }
if onshow is not None:
self.Handler.AddShowCallback(self.Id, (lambda menu = (ref(self),): onshow(menu())))
if wxMSW:
self.Handler.hwndMap[self.HMenu] = self
self._windowless = windowless
self.UpdateSkin()
def SetWindowless(self, val):
self._windowless = val
Windowless = property((lambda self: self._windowless), SetWindowless)
def IsShown(self):
if not self.popup:
return False
try:
return self.popup.IsShown()
except AttributeError:
return False
def UpdateSkin(self):
mbskin = skin.get('MenuBar', None)
if 'wxMac' in wx.PlatformInfo and not mbskin and mbskin.get('menuskin', None) is None or mbskin.get('mode', 'skin').lower() == 'native':
self.skin = S(native = True)
native = True
else:
self.skin = skin.get(mbskin.menuskin)
native = False
self.skin.native = False
if not native and not hasattr(self, 'popup'):
self.popup = MenuPopupWindow(self.Window, self)
elif not native:
self.popup.UpdateSkin()
self.popup.vlist.UpdateSkin()
elif native:
if hasattr(self, 'popup'):
self.popup.Destroy()
del self.popup
def Display(self, caller = None):
self.PopupMenu(caller.ScreenRect)
def dismiss_old(self):
menuref = UMenu.last_menu
if menuref is None:
return None
menu = menuref()
if menu is not None and not wx.IsDestroyed(menu):
menu.Dismiss()
UMenu.last_menu = None
def PopupMenu(self, pos = None, submenu = False, event = None):
if not submenu:
self.dismiss_old()
if event is not None:
event.Skip(False)
if 'wxMSW' in wx.PlatformInfo and self._windowless:
_smokeFrame = _smokeFrame
import gui.native.win.wineffects
if _smokeFrame:
_smokeFrame.SetFocus()
try:
onshow = self._onshow
except AttributeError:
pass
onshow(self)
traceguard.__enter__()
try:
return popup(pos)
finally:
pass
def Dismiss(self):
if not self.skin.get('native', False) and not wx.IsDestroyed(self.popup):
return self.popup.vlist.Dismiss()
if wxMSW:
if hasattr(wx.Menu, 'GetHMenu'):
GetHMenu = wx.Menu.GetHMenu
else:
def GetHMenu(self):
cast = cast
POINTER = POINTER
c_long = c_long
import ctypes
p = cast(int(self.this), POINTER(c_long))
return p[25]
HMenu = property(GetHMenu)
def AddItem(self, text = '', bitmap = None, callback = None, id = -1):
return self._additem(text, bitmap, callback, id = id)
def AddItemAt(self, position, text = '', bitmap = None, callback = None, id = -1):
return self._additem(text, bitmap, callback, id = id, position = position)
def Append(self, id, text, bitmap = None, callback = None):
return self._additem(text, bitmap, callback, id = id)
def AddCheckItem(self, text, callback = None):
return self._additem(text, callback = callback, kind = ITEM_CHECK)
def AddRadioItem(self, text, callback = None):
return self._additem(text, callback = callback, kind = ITEM_RADIO)
def AddPrefCheck(self, pref, text, help = '', updatenow = True):
profile = profile
import common
prefs = profile.prefs
def callback():
prefs[pref] = not prefs[pref]
item = self._additem(text, callback = callback, kind = ITEM_CHECK)
prefs.link((pref,), (lambda val: item.Check(val)), obj = self)
return item
def AppendLazyMenu(self, name, callback, bitmap = None):
if not callable(callback):
raise TypeError, repr(callback)
menu = UMenu(self.Window)
return self.AddSubMenu(menu, name, bitmap = bitmap, onshow = (lambda menu = (menu,): callback(menu)))
def _additem(self, text, bitmap = None, callback = None, kind = ITEM_NORMAL, id = -1, position = None):
item = MenuItem(self, id, text, kind = kind)
id = item.Id
if bitmap is not None:
self.SetItemBitmap(item, bitmap)
if callback is not None:
self.SetCallback(id, callback)
if position is None:
self.AppendItem(item)
else:
self.InsertItem(position, item)
return item
def SetCallback(self, id, callback):
callback = lambda cb = (callback,): self._refresh_callback(cb)
self.cbs[id] = callback
self.Handler.AddCallback(id, callback)
def _refresh_callback(self, cb):
m = self._parentmenu
if m is None:
m = self
else:
while m._parentmenu:
m = m._parentmenu
if hasattr(m, '_button'):
if wx.IsDestroyed(m._button):
del m._button
else:
m._button.Refresh()
m._button.Update()
self.Window.Refresh()
self.Window.Update()
return cb()
def AddSubMenu(self, submenu, label, bitmap = None, onshow = None):
submenu._parentmenu = self
if onshow is not None:
self.Handler.AddShowCallback(submenu.Id, onshow)
item = self.AppendSubMenu(submenu, label)
if bitmap is not None:
self.SetItemBitmap(item, bitmap)
return item
def SetItemBitmap(self, item, bitmap):
if self.skin.native and bitmap.Ok():
bitmap = bitmap.ResizedSmaller(16)
item.SetBitmap(bitmap)
def AddSep(self):
return self.AppendItem(MenuItem(self))
def AddSepAt(self, i):
return self.InsertItem(i, MenuItem(self))
def RemoveItems(self, items):
return [ self.RemoveItem(item) for item in items ]
def RemoveAll(self):
return self.RemoveItems(list(self))
def DestroyAll(self):
for item in self.RemoveAll():
item.Destroy()
def GetItemById(self, id):
for i, myitem in enumerate(self):
if myitem.Id == id:
return myitem
continue
def IndexOf(self, item):
id = item.Id
for i, myitem in enumerate(self):
if myitem.Id == id:
return i
continue
return -1
def Break(self):
raise NotImplementedError('skinned menus cannot break')
def Top(self):
w = self.Window
while not isinstance(w, wx.TopLevelWindow):
try:
w = getattr(w, 'Window', getattr(w, 'ParentWindow', w.Parent))
continue
except AttributeError:
print '***', w, '***'
raise
continue
None<EXCEPTION MATCH>AttributeError
return w
Top = property(Top)
def Handler(self):
return menuEventHandler(self.Top)
Handler = property(Handler)
def _activate_item(self, item):
return self.popup.vlist._activate_item(item)
def __iter__(self):
return iter(self.GetMenuItems())
def __getitem__(self, n):
return self.GetMenuItems()[n % len(self)]
def __len__(self):
return len(self.GetMenuItems())
def __contains__(self, item):
for i in self:
if i.Id == item.Id:
return True
continue
return False
def __repr__(self):
return '<%s %r>' % (self.__class__.__name__, self.Title)
class UMenuBar(wx.MenuBar):
def __init__(self, parent, skinkey = 'MenuBar'):
wx.MenuBar.__init__(self)
self.toptitles = { }
self.skinkey = skinkey
self.accelremoves = Delegate()
self.panel = SkinnedPanel(parent, 'MenuBar')
self.panel.UpdateSkin = self.UpdateSkin
self.panel.Hide()
self.UpdateSkin()
def UpdateSkin(self):
s = self.skin = skin.get(self.skinkey)
if not s.get('mode', 'skin').lower() == 'native':
pass
self.native = 'wxMac' in wx.PlatformInfo
if not hasattr(self, 'panel'):
return None
if self.native:
for child in self.panel.Children:
traceguard.__enter__()
try:
child.Destroy()
finally:
pass
self.panel.Hide()
self.ParentWindow.Top.SetMenuBar(self)
else:
self._constructSkinElements()
win = self.ParentWindow.Top
if win.MenuBar is self:
win.SetMenuBar(None)
self.panel.Sizer.Layout()
self.panel.Show(self.IsShown())
def Append(self, menu, title, onshow = None):
self.toptitles[menu] = title
i = wx.MenuBar.Append(self, menu, title)
if not self.native:
self._constructSkinElements()
if onshow is not None:
self.Handler.AddShowCallback(menu.Id, (lambda menu = (menu,): onshow(menu)))
return i
def _constructSkinElements(self):
s = self.skin
p = self.panel
p.bg = s.get('background', SkinColor(wx.WHITE))
pad = p.padding = s.get('padding', wx.Point(0, 0))
for child in list(p.Children):
child.Hide()
child.Destroy()
v = wx.BoxSizer(wx.VERTICAL)
h = wx.BoxSizer(wx.HORIZONTAL)
v.Add(h, 1, wx.EXPAND | wx.TOP | wx.BOTTOM, pad.y)
p.Sizer = s.get('margins', Margins()).Sizer(v)
self.buttons = []
addb = self.buttons.append
menus = self.Menus
nummenus = len(self.Menus)
for menu, label in enumerate(menus):
del menu.OnDismiss[:]
label = self.toptitles.get(menu, label)
button = UberButton(p, -1, skin = s.itemskin, label = label, type = 'menu', menu = menu, menubarmode = True)
addb(button)
menu._next = menus[(i + 1) % nummenus][0]
menu._prev = menus[i - 1][0]
menu._button = button
(h.AddMany,)((lambda .0: for b in .0:
(b, 0, wx.EXPAND | wx.LEFT, pad.x))(self.buttons))
self._bindAccelerators()
def Show(self, val):
native = self.native
if native:
win = self.ParentWindow.Top
self.panel.Hide()
if val and win.MenuBar is not self:
win.MenuBar = self
elif not val and win.MenuBar is self:
win.MenuBar = None
else:
self.panel.Show(val)
def _bindAccelerators(self):
accelrems = self.accelremoves
parentproc = self.ParentWindow.ProcessEvent
keybind = self.KeyCatcher.OnDown
accelrems()
del accelrems[:]
for menu in self:
for item in menu:
accel = GetAccelText(item)
if accel:
cb = lambda e, item = item, menu = (menu,): parentproc(menuevt(item))
accelrems.append(keybind(accel, cb))
continue
def KeyCatcher(self):
try:
return self.ParentWindow._keycatcher
except AttributeError:
k = self.ParentWindow._keycatcher = KeyCatcher(self.ParentWindow)
return k
KeyCatcher = property(KeyCatcher)
def __len__(self):
return self.GetMenuCount()
def __iter__(self):
return []([ self.GetMenu(i) for i in xrange(self.GetMenuCount()) ])
def SizableWindow(self):
return self.panel
SizableWindow = property(SizableWindow)
def ParentWindow(self):
return self.panel.Parent
ParentWindow = property(ParentWindow)
def Handler(self):
return menuEventHandler(self.panel.Top)
Handler = property(Handler)
registered_activate_app = False
def _activateapp(e):
vlist = MenuListBox._lastvlist()
if vlist is not None and not wx.IsDestroyed(vlist) and not wx.IsDestroyed(vlist.menu):
if vlist.menu and vlist.menu._windowless and not e.GetActive():
vlist.DismissRoot()
class MenuListBox(SkinVListBox):
def __init__(self, parent, menu):
global registered_activate_app
SkinVListBox.__init__(self, parent, style = wx.NO_BORDER | wx.FULL_REPAINT_ON_RESIZE | wx.WANTS_CHARS)
self.menu = menu
self.UpdateSkin()
self.timer = wx.PyTimer(self._on_submenu_timer)
Bind = self.Bind
Bind(wx.EVT_MOUSE_EVENTS, self._mouseevents)
Bind(wx.EVT_MOUSE_CAPTURE_CHANGED, self._capturechanged)
Bind(wx.EVT_LISTBOX, self._listbox)
Bind(wx.EVT_KEY_DOWN, self._keydown)
self.mouseCallbacks = {
wx.wxEVT_MOTION: self._motion,
wx.wxEVT_RIGHT_DOWN: self._rdown,
wx.wxEVT_LEFT_DOWN: self._ldown,
wx.wxEVT_LEFT_UP: self._lup }
MenuListBox._lastvlist = ref(self)
if not registered_activate_app:
wx.GetApp().Bind(wx.EVT_ACTIVATE_APP, _activateapp)
registered_activate_app = True
def reassign(self, menu):
self.menu = menu
menuOpenDelayMs = prefprop('menus.submenu_delay', 250)
def __repr__(self):
return '<%s for %r>' % (self.__class__.__name__, self.menu)
def ParentPopup(self):
pmenu = self.menu._parentmenu
return None if pmenu is None else pmenu.popup.vlist
ParentPopup = property(ParentPopup)
def CalcSize(self):
self.SetItemCount(len(self.menu))
height = 0
dc = wx.MemoryDC()
dc.Font = self.font
s = self.skin
padx = self.padding[0]
iconsize = s.iconsize
subw = s.submenuicon.Width
sepheight = s.separatorimage.Size.height
itemheight = self.itemheight
textExtent = dc.GetTextExtent
labelw = accelw = 0
for item in self.menu:
if item.Kind == ITEM_SEPARATOR:
height += sepheight
continue
height += itemheight
labelw = max(labelw, textExtent(item.Label)[0])
accelw = max(accelw, textExtent(item.AccelText)[0])
self.accelColumnX = padx + iconsize + padx + padx + labelw + padx
width = self.accelColumnX + padx + max(accelw, subw) + padx
self.MinSize = self.Size = wx.Size(width, height)
def OnDrawItem(self, dc, rect, n):
item = self.menu[n]
kind = item.Kind
s = self.skin
iconsize = s.iconsize
submenuicon = s.submenuicon
padx = self.padding.x
selected = self.IsSelected(n)
drawbitmap = dc.DrawBitmap
drawlabel = dc.DrawLabel
if kind == ITEM_SEPARATOR:
s.separatorimage.Draw(dc, rect, n)
else:
dc.Font = self.font
if not item.IsEnabled():
fg = 'disabled'
elif selected:
fg = 'selection'
else:
fg = 'normal'
dc.TextForeground = getattr(s.fontcolors, fg)
grect = Rect(*rect)
grect.width = padx + iconsize + padx
bmap = item.Bitmap
if bmap and bmap.Ok():
bmap = bmap.ResizedSmaller(iconsize)
drawbitmap(bmap, grect.HCenter(bmap), rect.VCenter(bmap), True)
if item.IsCheckable() and item.IsChecked():
if bmap:
checkx = grect.Right - s.checkedicon.Width
else:
checkx = grect.HCenter(s.checkedicon)
if kind == ITEM_CHECK:
drawbitmap(s.checkedicon, checkx, rect.VCenter(s.checkedicon), True)
elif kind == ITEM_RADIO:
drawbitmap(s.checkedicon, checkx, rect.VCenter(s.checkedicon), True)
rect.Subtract(left = iconsize + 3 * padx)
drawlabel(item.Label, rect, indexAccel = item.Text.split('\t')[0].find('&'), alignment = ALIGN_CENTER_VERTICAL)
rect.Subtract(right = submenuicon.Width + padx)
if item.SubMenu is not None:
drawbitmap(submenuicon, rect.Right, rect.VCenter(submenuicon), True)
acceltext = item.AccelText
if acceltext:
rect.x = self.accelColumnX + padx
drawlabel(acceltext, rect, alignment = ALIGN_CENTER_VERTICAL)
def OnDrawBackground(self, dc, rect, n):
s = self.skin
bgs = s.backgrounds
bgname = None if self.menu[n].Kind != ITEM_SEPARATOR and self.IsSelected(n) else 'item'
bg = getattr(bgs, bgname, None)
if bg:
bg.Draw(dc, rect, n)
def PaintMoreBackground(self, dc, rect):
g = self.skin.backgrounds.gutter
if g:
g.Draw(dc, Rect(rect.x, rect.y, self.skin.iconsize + self.padding.x * 2, rect.height))
def OnMeasureItem(self, n):
item = self.menu[n]
kind = item.Kind
if kind == ITEM_SEPARATOR:
return self.sepheight
else:
return self.itemheight
def OnPopup(self):
if self.menu._windowless and self.TopMenu == self.menu:
if not hasattr(self, 'traytimer'):
self.traytimer = UMenuTrayTimer(self)
self.traytimer.Start(50)
if not self.menu._parentmenu:
self._grabkeyboard()
if wx.LeftDown():
self._leftbuttondown = True
if not self.HasCapture():
self.CaptureMouse()
self.SetCursor(StockCursor(CURSOR_DEFAULT))
self.SetFocus()
def Dismiss(self):
if hasattr(self, 'traytimer'):
self.traytimer.Stop()
if self.menu._childmenu:
self.menu._childmenu.Dismiss()
self.menu._childmenu = None
while self.HasCapture():
self.ReleaseMouse()
self.Parent.Hide()
m = self.menu
if m._parentmenu is None:
if hasattr(self, 'focusHandler'):
self.focusHandler.close()
del self.focusHandler
wx.CallAfter(self.menu.OnDismiss)
else:
m._parentmenu._childmenu = None
def DismissRoot(self):
self.TopMenu.Dismiss()
def TopMenu(self):
m = self.menu
while m._parentmenu is not None:
m = m._parentmenu
return m
TopMenu = property(TopMenu)
def UpdateSkin(self):
self.SetMargins(wx.Point(0, 0))
s = self.skin = self.menu.skin
self.sepheight = s.separatorimage.Size.height
try:
self.font = s.font
except KeyError:
self.font = default_font()
self.fontheight = s.font.Height
try:
self.padding = s.padding
except Exception:
self.padding = wx.Point(3, 3)
self.itemheight = int(self.fontheight + self.padding.y * 2)
self.Background = s.backgrounds.menu
def Window(self):
return self.menu.Window
Window = property(Window)
def _grabkeyboard(self):
if 'wxMSW' in wx.PlatformInfo:
self._focusWin = wx.Window.FindFocus()
elif 'wxGTK' in wx.Platform:
self._focusWin = self
else:
self._focusWin = None
f = self._focusWin
if f:
self.focusHandler = FocusHandler(self, f)
def _showsubmenu(self, i, highlight = False):
item = self.menu[i]
submenu = item.SubMenu
child = self.menu._childmenu
if child is submenu:
return None
if child is not None:
if child:
child.Dismiss()
self.menu._childmenu = None
if i != -1 and submenu is not None:
r = self.ClientRect
r.Y = self.GetItemY(i)
r.Height = self.OnMeasureItem(i)
self.menu._childmenu = submenu
submenu._parentmenu = self.menu
submenu._parentindex = i
submenu.PopupMenu(r.ToScreen(self), submenu = True)
if highlight:
submenu.popup.vlist.Selection = 0
def _on_submenu_timer(self):
i = self.Selection
if i != -1 and self.IsShown() and FindWindowAtPointer() is self:
self._showsubmenu(i)
def _listbox(self, e):
self.timer.Start(self.menuOpenDelayMs, True)
def _emit_menuevent(self, id, type = wx.wxEVT_COMMAND_MENU_SELECTED):
event = wx.CommandEvent(type, id)
self.menu.Handler.AddPendingEvent(event)
def _mouseevents(self, e, wxEVT_MOTION = wxEVT_MOTION, FindWindowAtPoint = FindWindowAtPoint, UberButton = UberButton):
rect = self.ClientRect
pt = e.Position
if not rect.Contains(pt):
menu = self.ParentPopup
oldmenu = self
while menu:
pt = menu.ScreenToClient(oldmenu.ClientToScreen(pt))
if menu.ClientRect.Contains(pt):
(e.m_x, e.m_y) = pt
return menu._mouseevents(e)
oldmenu = menu
menu = menu.ParentPopup
try:
button = self.TopMenu._button
except AttributeError:
pass
if e.GetEventType() == wxEVT_MOTION:
ctrl = FindWindowAtPoint(self.ClientToScreen(e.Position))
if ctrl is not None:
if getattr(self, '_motionswitch', -1) is ctrl:
self._motionswitch = None
self.DismissRoot()
ctrl.menu._showquick = True
ctrl.OnLeftDown()
elif isinstance(ctrl, UberButton) and ctrl.menubarmode and hasattr(ctrl, 'menu'):
if ctrl.Parent is button.Parent and ctrl is not button:
self._motionswitch = ctrl
try:
cb = self.mouseCallbacks[e.EventType]
except KeyError:
pass
cb(e)
def _motion(self, e):
p = e.Position
i = None if self.ClientRect.Contains(p) else -1
s = self.Selection
if i != s:
p = self.ParentPopup
if p is not None:
pi = getattr(self.menu, '_parentindex', None)
if pi is not None and p.Selection != pi:
p.Selection = pi
self.SetSelection(i)
self._emit_lbox_selection(i)
def LeafMenu(self):
s = self.menu
while s._childmenu:
s = s._childmenu
return s
LeafMenu = property(LeafMenu)
def _keydown(self, e):
self = self.LeafMenu.popup.vlist
code = e.KeyCode
i = self.Selection
j = -1
m = self.menu
if code == wx.WXK_DOWN:
j = (i + 1) % len(m)
while j != i and m[j].Kind == wx.ITEM_SEPARATOR:
j = (j + 1) % len(m)
elif code == wx.WXK_UP:
if i == -1:
i = len(m)
j = (i - 1) % len(m)
while j != i and m[j].Kind == wx.ITEM_SEPARATOR:
j = (j - 1) % len(m)
elif code == wx.WXK_RETURN:
return self._activate_item(i, submenu = True, highlight = True)
elif code == wx.WXK_RIGHT:
if i == -1:
pass
elif m[i].SubMenu is not None:
self.timer.Stop()
return self._showsubmenu(i, highlight = True)
while m._parentmenu:
m = m._parentmenu
next = getattr(m, '_next', None)
if next is not None:
wx.CallAfter(self.DismissRoot)
next._showquick = True
wx.CallAfter(next._button.OnLeftDown)
elif code == wx.WXK_ESCAPE:
self.Dismiss()
elif code == wx.WXK_LEFT:
if m._parentmenu:
self.Dismiss()
else:
prev = getattr(self.menu, '_prev', None)
if prev is not None:
wx.CallAfter(self.DismissRoot)
prev._showquick = True
wx.CallAfter(prev._button.OnLeftDown)
elif code < 256:
self._on_char(unichr(e.UnicodeKey))
if j != -1:
self.SetSelection(j)
def _on_char(self, char):
char = char.lower()
items = []
for item in self.menu:
amp_char = GetAmpChar(item)
if amp_char is not None and char == amp_char.lower():
return self._activate_item(item, submenu = True, highlight = True)
continue
items = []
for i in rotated(range(0, len(self.menu)), -(self.Selection) - 1):
item = self.menu[i]
label_text = item.GetItemLabelText()
if label_text and label_text[0].lower() == char:
items.append(i)
continue
if len(items) == 1:
self._activate_item(items[0], submenu = True, highlight = True)
elif len(items) > 1:
self.SetSelection(items[0])
def _rdown(self, e):
p = e.Position
rect = self.ClientRect
if not rect.Contains(p):
return self.DismissRoot()
def _ldown(self, e):
p = e.Position
rect = self.ClientRect
if not rect.Contains(p):
return self.DismissRoot()
i = self.HitTest(p)
if i != -1:
if self.menu[i].SubMenu is not None:
self.timer.Stop()
return self._showsubmenu(i)
def _lup(self, e):
p = e.Position
i = self.HitTest(e.Position)
if self.ClientRect.Contains(p):
self._activate_item(i)
else:
ctrl = FindWindowAtPointer()
if not isinstance(ctrl, UberButton) or not (ctrl.type == 'menu'):
self.DismissRoot()
def _activate_item(self, i, submenu = False, highlight = False):
if isinstance(i, int):
if i == -1:
return None
item = self.menu[i]
else:
item = i
i = self.menu.IndexOf(item)
if submenu:
if item.SubMenu is not None:
self.timer.Stop()
if not self.Selection == i:
self.SetSelection(i)
return self._showsubmenu(i, highlight = highlight)
if item.Kind != ITEM_SEPARATOR and item.IsEnabled() and item.SubMenu is None:
if item.IsCheckable():
item.Check(not item.IsChecked())
self._emit_menuevent(item.Id)
self.DismissRoot()
def _capturechanged(self, e):
def active():
try:
if self.menu._windowless or not hasattr(self.menu.Window.Top, 'IsActive'):
return True
else:
return self.menu.Window.Top.IsActive()
except Exception:
print_exc()
return True
((None,), wx.CallAfter)((lambda : None if not active() else None))
class MenuWindowBase(object):
def __init__(self, parent, menu):
self.vlist = MenuListBox(self, menu)
self.UpdateSkin()
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
self.Bind(wx.EVT_PAINT, self._paint)
def reassign(self, parent, menu):
self.Reparent(parent)
self.vlist.reassign(menu)
def _paint(self, e):
dc = wx.BufferedPaintDC(self)
self.bg.Draw(dc, self.ClientRect)
def UpdateSkin(self):
s = self.skin = self.vlist.menu.skin
if self.Sizer and not wx.IsDestroyed(self.Sizer):
self.Sizer.Clear()
self.framesize = s.get('framesize', skin.ZeroMargins)
self.Sizer = self.framesize.Sizer(self.vlist)
self.bg = s.frame
def PopupMenu(self, pos = None, submenu = False):
v = self.vlist
v.menu.Handler._menu_open(menu = v.menu)
v.SetSelection(-1)
v.CalcSize()
self.Fit()
self.Sizer.Layout()
if isinstance(self.bg, SplitImage4):
self.Cut(self.bg.GetBitmap(self.Size))
else:
self.Cut()
pos = None if pos is None else pos
try:
try:
disp = Monitor.GetFromPoint(pos[:2]).Geometry
except Exception:
disp = Monitor.GetFromPoint(pos.BottomRight).Geometry
except Exception:
print_exc()
log.critical('could not find display for %s, falling back to zero', pos)
disp = Monitor.All()[0].Geometry
size = self.Size
rects = []
add = lambda *seq: []([ RectPS(p, size) for p in seq ])
singlepoint = len(pos) == 2
offset = (None, None) if singlepoint else 0
if singlepoint:
pos = wx.RectPS(pos, (0, 0))
w = Point(size.width - offset, 0)
h = Point(0, size.height - offset)
wh = Point(size.width - offset, size.height - offset)
difftop = Point(0, self.framesize.top)
diffbottom = Point(0, self.framesize.bottom)
if submenu:
add(pos.TopRight - difftop, pos.TopLeft - w - difftop, (pos.BottomRight - h) + diffbottom, (pos.BottomLeft - wh) + diffbottom)
else:
add(pos.BottomLeft, pos.TopLeft - h, pos.BottomRight - w, pos.TopRight - h, pos.TopRight - wh, pos.BottomLeft - h)
for rect in rects:
if disp.ContainsRect(rect):
self._showat(rect)
return None
continue
rect = rects[0]
if hasattr(v.menu, '_button'):
brect = v.menu._button.ScreenRect
if rect.Intersects(brect):
rect.Offset((brect.Width, 0))
self._showat(rect)
def _showat(self, rect, nofade = False):
self.SetRect(rect)
self.EnsureInScreen()
if nofade:
self.Show()
elif getattr(self.vlist.menu, '_showquick', False):
self.vlist.menu._showquick = False
self.Show()
else:
fadein(self, 'xfast')
if wxMSW:
CallLater((1,), (lambda : None if self else None))
self.vlist.OnPopup()
class MenuPopupWindow(MenuWindowBase, wx.PopupWindow):
def __init__(self, parent, menu):
wx.PopupWindow.__init__(self, parent)
MenuWindowBase.__init__(self, parent, menu)
class MenuFrameWindow(MenuWindowBase, wx.Frame):
def __init__(self, parent, menu):
wx.Frame.__init__(self, parent)
MenuWindowBase.__init__(self, parent, menu)
from weakref import WeakValueDictionary
class MenuEventHandler(wx.EvtHandler):
def __init__(self, parentFrame):
wx.EvtHandler.__init__(self)
parentFrame.PushEventHandler(self)
self.Bind(wx.EVT_MENU, self._MenuEventHandler__menu)
if 'wxMac' not in wx.PlatformInfo:
self.Bind(wx.EVT_MENU_OPEN, self._menu_open)
if 'wxMSW' in wx.PlatformInfo:
parentFrame.BindWin32(WM_INITMENUPOPUP, self._initmenupopup)
self.cbs = WeakValueDictionary()
self.showcbs = { }
if wxMSW:
self.hwndMap = WeakValueDictionary()
def AddCallback(self, id, callback):
self.cbs[id] = callback
def AddShowCallback(self, id, callback):
self.showcbs[id] = callback
def __menu(self, e):
id = e.Id
try:
cb = self.cbs[id]
except KeyError:
e.Skip()
cb()
def _menu_open(self, e = None, menu = None):
if e is not None:
e.Skip()
menu = e.Menu
if menu is None:
return None
try:
cb = self.showcbs[menu.Id]
except KeyError:
pass
cb()
if wxMSW:
def _initmenupopup(self, hWnd, msg, wParam, lParam):
try:
menu = self.hwndMap[wParam]
except KeyError:
return None
if menu._parentmenu:
evt = PyCommandEvent(wxEVT_MENU_OPEN, menu.Id)
evt.Menu = menu
menu.Handler.ProcessEvent(evt)
class FocusHandler(wx.EvtHandler):
def __init__(self, menu, ctrl):
wx.EvtHandler.__init__(self)
self._menu = menu
self._ctrl = ctrl
self.Bind(wx.EVT_KEY_DOWN, self._menu._keydown)
self.Bind(wx.EVT_NAVIGATION_KEY, self._menu._keydown)
self.wantschars = bool(ctrl.WindowStyleFlag & wx.WANTS_CHARS)
if not self.wantschars:
ctrl.SetWindowStyleFlag(ctrl.WindowStyleFlag | wx.WANTS_CHARS)
ctrl.PushEventHandler(self)
def close(self):
ctrl = self._ctrl
ctrl.RemoveEventHandler(self)
f = ctrl.WindowStyleFlag
if not self.wantschars:
f = f & ~(wx.WANTS_CHARS)
ctrl.SetWindowStyleFlag(f)
def SetMenu(self, menu):
self._menu = menu
def OnKeyDown(self, event):
self._menu.OnKeyDown(event)
def menuEventHandler(f):
try:
return f._menuevthandler
except AttributeError:
h = f._menuevthandler = MenuEventHandler(f)
return h
from gui.toolbox.keynames import keynames, modifiernames
def menuevt(item):
return wx.CommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, item.Id)
def GetAccelText(item):
a = item.Accel
return None if not a else _getacceltext(a.Flags, a.KeyCode)
if not hasattr(wx, '_MenuItem'):
wx._MenuItem = wx.MenuItem
wx._MenuItem.AccelText = property(GetAccelText)
def GetAmpChar(item):
text = item.Text
amp_index = text.find('&')
if amp_index != -1 and amp_index < len(text) - 1:
return text[amp_index + 1]
def _getacceltext(modifiers, key, joinstr = '+'):
return [](_[1] + [
keynames.get(key, chr(key).upper())])
_getacceltext = memoize(_getacceltext)
from collections import deque
def rotated(iter, n):
d = deque(iter)
d.rotate(n)
return d